/*
 * Copyright 2012 Jonathan St-Michel <jonathan@abiwebz.net>.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package net.abiwebz.office.rm.database.security;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.prefs.Preferences;
import javax.swing.JButton;
import net.abiwebz.office.rm.database.DataConnections;
import net.abiwebz.office.rm.database.DatabaseDriver;
import net.abiwebz.office.rm.database.DatabaseDrivers;
import org.openide.DialogDescriptor;
import org.openide.DialogDisplayer;
import org.openide.LifecycleManager;
import org.openide.NotifyDescriptor;
import org.openide.util.NbPreferences;

/**
 *
 * @author Jonathan St-Michel <jonathan@abiwebz.net>
 */
public class SecurityManager implements ActionListener {

    private static SecurityManager instance;
    private String user; // Connected user

    /**
     * Create new instance of SecurityManager.
     *
     * @return New instance of SecurityManager
     */
    public static SecurityManager create() {
        SecurityManager.instance = new SecurityManager();
        return SecurityManager.instance;
    }

    /**
     * Return default instance of SecurityManager class. If no instance exist
     * because SecurityManager.create() was not called before, the function will
     * try to create an instance before returning it.
     *
     * @return Default SecurityManager instance
     */
    public static SecurityManager get() {
        if (SecurityManager.instance == null) { //No instance is created
            return SecurityManager.create();
        } else { //We already have an existing instance
            return SecurityManager.instance;
        }
    }
    //==================== END OF STATIC FUNCTIONS =============================
    private DialogDescriptor dd;
    private LoginPanel loginPanel;
    private JButton connect;
    private JButton cancel;
    private DatabaseDriver driver;
    private String connectionString;
    private String location;

    public void login() {
        login(NbPreferences.forModule(DatabaseDrivers.class).get("database.connection", "online"));
    }

    public void login(String location) {
        this.location = location;
        // Initialize data for connection
        boolean driverReady = initDriver(location);
        if (driverReady) {
            // Initialize the buttons for the descriptor
            connect = new JButton("Connect");
            cancel = new JButton("Cancel");

            // Initialize the descriptor with the LoginPanel loaded
            // at this state it is not visible to user
            loginPanel = new LoginPanel();
            dd = new DialogDescriptor(loginPanel, "Login", true, this);
            dd.setClosingOptions(new Object[]{}); // Nothing close the dialog by default

            // Create the listener for the closing window - Quit the platform
            dd.addPropertyChangeListener(new PropertyChangeListener() {

                @Override
                public void propertyChange(PropertyChangeEvent evt) {
                    if (evt.getPropertyName().equals("value")) { // Check the right property
                        if (NotifyDescriptor.CLOSED_OPTION.equals(evt.getNewValue())) {
                            LifecycleManager.getDefault().exit();
                        }
                    }
                }
            });

            dd.setMessageType(NotifyDescriptor.PLAIN_MESSAGE); // Don't show Message icons 
            dd.setOptions(new Object[]{connect, cancel}); // Use predefined buttons
            dd.createNotificationLineSupport().setInformationMessage("Please enter your credentials !");
            // Insert the display into a Thread Queue and show when ready
            DialogDisplayer.getDefault().notifyLater(dd);
        } else {
            // TODO Create error message and quit
            System.out.println("Driver is not ready!!!");
            LifecycleManager.getDefault().exit();
        }
    }

    private boolean initDriver(String location) {
        Preferences p = NbPreferences.forModule(DatabaseDrivers.class);
        String prefix = "database.driver." + location + ".";
        String id = p.get(prefix + "id", "");
        String jdbc = p.get(prefix + "jdbc", "");
        if(id.isEmpty() || jdbc.isEmpty()){
            return false;
        }
        else{
            driver = DatabaseDrivers.get().find(id);
            if(driver == null)
                return false;
            connectionString = jdbc;
        }
        return true;
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == cancel) {
            LifecycleManager.getDefault().exit();
        } else {
            char[] pwd = new char[]{};
            try {
                pwd = loginPanel.getPassword();
                Connection c = this.driver.createConnection(connectionString, loginPanel.getUsername(), pwd);
                
                if(this.location.equals("online"))
                    DataConnections.get().setOnlineConnection(c);
                else
                    DataConnections.get().setOfflineConnection(c);
                dd.setClosingOptions(null);
                
            } catch (SQLException ex) {
                dd.getNotificationLineSupport().setErrorMessage(this.driver.getErrorMessage(ex.getErrorCode()));
            }
            // Clear password
            for(int i = 0; i < pwd.length; i++){
                pwd[i] = 0;
            }
        }
    }
}
